package com.gitee.huanminabc.utils_tools.file_tool.itext7;

import com.gitee.huanminabc.jcommon.file.IoStreamUtil;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.Image;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * @description: pdf发票  将所有发票图片按照顺序添加到pdf中
 * 如果报错: Image format cannot be recognized.   表示图片格式不支持, 请使用png格式 或者者jpg格式
 * @author: huanmin
 * @create: 2025-04-22 14:23
 **/
@Slf4j
public class PDFInvoiceList {
    private final PdfWriter writer;
    private final Document document;
    private final PdfDocument pdfDocument;
    private HttpServletResponse response;
    private String filePath;

    private PDFInvoiceList(PdfWriter writer, Document document, PdfDocument pdfDocument, HttpServletResponse response) {
        this.writer = writer;
        this.document = document;
        this.pdfDocument = pdfDocument;
        this.response = response;
    }

    private PDFInvoiceList(PdfWriter writer, Document document, PdfDocument pdfDocument, String filePath) {
        this.writer = writer;
        this.document = document;
        this.pdfDocument = pdfDocument;
        this.filePath = filePath;
    }

    //1.创建pdf文档
    public static PDFInvoiceList createWebPdfDocument(HttpServletResponse response, String fileName) {
        try {
            //设置响应头
            response.setContentType("application/pdf");
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
            //创建pdf文档
            PdfWriter writer = new PdfWriter(response.getOutputStream());
            PdfDocument pdfDocument = new PdfDocument(writer);
            Document document = new Document(pdfDocument);
            return new PDFInvoiceList(writer, document, pdfDocument, response);
        } catch (Exception e) {
            throw new IllegalArgumentException("创建PDF文档失败", e);
        }
    }

    //创建本地pdf文档
    public static PDFInvoiceList createLocalPdfDocument(String filePath) {
        try {
            //创建pdf文档
            PdfWriter writer = new PdfWriter(Paths.get(filePath).toFile());
            PdfDocument pdfDocument = new PdfDocument(writer);
            Document document = new Document(pdfDocument);
            return new PDFInvoiceList(writer, document, pdfDocument, filePath);
        } catch (Exception e) {
            throw new IllegalArgumentException("创建PDF文档失败", e);
        }
    }

    //创建本地pdf文档 OutputStream
    public static PDFInvoiceList createLocalPdfDocument() {
        try {
            String temporaryDirectory = System.getProperty("user.dir") + File.separator + UUID.randomUUID() + ".pdf";
            //创建pdf文档
            PdfWriter writer = new PdfWriter(temporaryDirectory);
            PdfDocument pdfDocument = new PdfDocument(writer);
            Document document = new Document(pdfDocument);
            return new PDFInvoiceList(writer, document, pdfDocument, temporaryDirectory);
        } catch (Exception e) {
            throw new IllegalArgumentException("创建PDF文档失败", e);
        }
    }


    //2.添加图片到pdf文档,自适应,本地路径方式
    public PDFInvoiceList addImageToPdf(List<String> imagePathList) {
        try {
            for (int i = 0; i < imagePathList.size(); i++) {
                String imagePath = imagePathList.get(i);
                //创建图片对象
                Image image = new Image(ImageDataFactory.create(imagePath));
                image.setAutoScale(true);
                //添加图片到pdf文档
                document.add(image);
                //偶数页添加分页符
                if (i % 2 == 1) {
                    document.add(new AreaBreak());
                }
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("添加图片到PDF文档失败", e);
        }
        return this;
    }

    //添加图片到pdf文档,自适应,字节方式,同一组图片放在一起
    public PDFInvoiceList addGroupImageToPdf(List<byte[]> imageBytesList) {
        try {
            for (int i = 0; i < imageBytesList.size(); i++) {
                byte[] bytes = imageBytesList.get(i);
                //创建图片对象
                Image image = new Image(ImageDataFactory.create(bytes));
                image.setAutoScale(true);
                //添加图片到pdf文档
                document.add(image);
                //偶数页添加分页符
                if (i % 2 == 1) {
                    document.add(new AreaBreak());
                }
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("添加图片到PDF文档失败", e);
        }
        return this;
    }

    //添加图片到pdf文档,自适应,网络路径方式,同一组图片放在一起
    public PDFInvoiceList addGroupNetImageToPdf(List<URI> imagePaths) {
        if (imagePaths == null || imagePaths.isEmpty()) {
            throw new IllegalArgumentException("图片路径列表不能为空");
        }
        try {
            for (int i = 0; i < imagePaths.size(); i++) {
                URI imagePath = imagePaths.get(i);
                // 确保URI有效
                URL imageUrl = imagePath.toURL();
                // 使用try-with-resources确保资源释放
                try (InputStream imageStream = imageUrl.openStream()) {
                    //转换为字节数组
                    byte[] bytes = IoStreamUtil.inputStreamToByte(imageStream);
                    ImageData imageData = ImageDataFactory.create(bytes);
                    Image image = new Image(imageData);
                    image.setAutoScale(true);
                    document.add(image);
                } catch (IOException e) {
                    throw new IllegalArgumentException(e);
                }
                //偶数页添加分页符
                if (i % 2 == 1) {
                    document.add(new AreaBreak());
                }
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("添加图片到PDF文档失败", e);
        }
        return this;
    }


    //返回byte[]
    public byte[] getPdfBytes() {
        try {
            writeToLocal();
            //读取文件内容
            return Files.readAllBytes(Paths.get(filePath));
        } catch (Exception e) {
            throw new IllegalArgumentException("获取PDF字节流失败", e);
        } finally {

            //删除临时文件
            if (filePath != null) {
                try {
                    Files.deleteIfExists(Paths.get(filePath));
                } catch (IOException e) {
                    log.error("删除临时文件失败 file:{}", filePath, e);
                }
            }
        }
    }

    //写入本地
    public void writeToLocal() {
        try {
            document.close();
            writer.close();
            pdfDocument.close();
        } catch (Exception e) {
            throw new IllegalArgumentException("写入本地PDF文档失败", e);
        }
    }

    //写入响应
    public void writeToResponse() {
        try {
            document.close();
            writer.close();
            pdfDocument.close();
            response.getOutputStream().flush();
        } catch (Exception e) {
            throw new IllegalArgumentException("写入响应PDF文档失败", e);
        }
    }


    public static void main(String[] args) {
        URI uri1 = URI.create("http://test-file.serviceshare.com/group1/M00/05/5A/wKgoVGe8LxyAUkwWAAB2ppkkKNM967.png");
        URI uri2 = URI.create("http://test-file.serviceshare.com/group1/M00/05/57/wKgoVGe2lRaAGMU1AAB2ppkkKNM507.png");
        List<URI> imagePaths = Arrays.asList(uri1, uri1, uri2, uri2, uri2);
        PDFInvoiceList pdfInvoiceList = PDFInvoiceList.createLocalPdfDocument("test.pdf");
        pdfInvoiceList.addGroupNetImageToPdf(imagePaths);
        pdfInvoiceList.writeToLocal();
    }


}
